package java模板模式;


/**
 * @author coderFu
 * @create 2022/3/3
 * 模板模式2
 *模板方法应该是由确定的步骤组成。这些步骤的顺序是固定的。
 * 基类与子类之间某些方法或者实现可以有所不同。模板方法应该是 final 的。
 *
 * 大多时候，子类的调用的方法是来自于超类。
 * 但是在模板模式中，超类的模板方法调用的方法却来至于子类，这就是著名的Hollywood原则-“don’t call us, we’ll call you”。
 *
 * 基类方法的默认实现被退化为钩子 Hooks 的概念，
 *他们被设计在子类中被重写，如果你期望一些方法在子类中不被重写，
 * 你可以让他们为 final。
 *
 */
abstract class ModelDemo2 {



    // 定义父类的模板方法+回调方法（加一层Restaurant类，Restaurant类
    //方法中调用client模板方法
    public void template(){
        before();
        appetite();
        after();
    }

    // 定义一个钩子方法 （空方法）， 可以选择性实现
    // 在盛饭前（一个空的实现）

    public void before(){};

    // 定义一个 抽象方法，告诉服务员饭量
    abstract void appetite();

    // 具体方法，盛饭后
    private void after(){
        //实际项目这里是共有的业务逻辑
        System.out.println("拿筷子，找桌子，开吃。。。");
    }


    /**
     * 食堂
     */
    static class Restaurant{

        /**
         * 打饭方法，前提是客户要告知服务员你的饭量，他会根据你的
         * 饭量给你盛饭
         * 回调
         * @param client 排队的客户
         */
        public void dozenRice(ModelDemo2 client){
            client.template();
        }
}

static class Test2{

        // 业务处理类，老王去打饭

    public static void main(String[] args) {

        Restaurant waiter = new Restaurant();

        waiter.dozenRice(new ModelDemo2() {

            @Override
            public void before() {
                System.out.println("对服务员吹胡子瞪眼");
            }

            @Override
            void appetite() {
                System.out.println("盛了一碗米饭");
            }
        });

    }

}


}
